package top.infopub.httpclient.cmpt;


import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;

import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.protocol.HttpContext;
import org.apache.http.ssl.SSLContextBuilder;


/**
 * 生成Http连接
 * @author Awoke
 * @version 2018年4月27日
 * @see ElideHttpClientGenerator
 * @since
 */
public class ElideHttpClientGenerator {

    // 连接池
    private PoolingHttpClientConnectionManager connectionManager;

    public ElideHttpClientGenerator() {
        SSLContext sslContext = null;
        try {
            sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
                @Override
                public boolean isTrusted(X509Certificate[] arg0, String arg1)
                    throws CertificateException {
                    return true;
                }
            }).build();
        }
        catch (Exception e) {
            throw new RuntimeException("can not create http client.", e);
        }
        SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext);
        Registry<ConnectionSocketFactory> reg = RegistryBuilder.<ConnectionSocketFactory> create().register(
            "http", PlainConnectionSocketFactory.INSTANCE).register("https", sslSocketFactory).build();
        connectionManager = new PoolingHttpClientConnectionManager(reg);
        connectionManager.setDefaultMaxPerRoute(100);

    }

    /**
     * 设置连接池大小
     * @param poolSize
     * @return 
     * @see
     */
    public ElideHttpClientGenerator setPoolSize(int poolSize) {
        connectionManager.setMaxTotal(poolSize);
        return this;
    }

    /**
     * 获得site对应的连接 
     * @param site
     * @return 
     * @see
     */
    public CloseableHttpClient getClient(Site site) {
        return generateClient(site);
    }

    private CloseableHttpClient generateClient(Site site) {
        if (site != null && site.getSslContextFactory() != null) {
            Registry<ConnectionSocketFactory> reg = RegistryBuilder.<ConnectionSocketFactory> create().register(
                "http", PlainConnectionSocketFactory.INSTANCE).register("https",
                site.getSslContextFactory()).build();
            connectionManager = new PoolingHttpClientConnectionManager(reg);
            connectionManager.setDefaultMaxPerRoute(50);
        }
        HttpClientBuilder httpClientBuilder = HttpClients.custom();
        if (site != null && site.getUserAgent() != null) {
            httpClientBuilder.setUserAgent(site.getUserAgent());
        }
        else {
            httpClientBuilder.setUserAgent("");
        }
        if (site == null || site.isUseGzip()) {
            httpClientBuilder.addInterceptorFirst(new HttpRequestInterceptor() {
                public void process(final HttpRequest request, final HttpContext context)
                    throws HttpException, IOException {
                    if (!request.containsHeader("Accept-Encoding")) {
                        request.addHeader("Accept-Encoding", "gzip");
                    }
                }
            });
        }
        SocketConfig socketConfig = SocketConfig.custom().setSoKeepAlive(true).setTcpNoDelay(true).build();
        httpClientBuilder.setDefaultSocketConfig(socketConfig);
        if (site != null) {
            // 失败重试
            httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(
                site.getRetryTimes(), true));
        }
        // 使用代理
        if (site != null && site.isEnableProxy()) {
            httpClientBuilder.setProxy(new HttpHost("192.168.31.174", 8888));
        }
        return httpClientBuilder.build();
    }

}
